#include "stdafx.h"
#include "Mediator.h"
#include "fbpMainFrame.h"

LUA_DEBUG_BEGIN

Mediator::Mediator(void) :
m_frame(NULL),
m_engine(new RemoteEngine(RemoteEngine::CLIENT_SIDE)),
m_breakpoints(m_engine),
m_sourceManager(m_engine)
{
    m_engine->SetOnRemoteCommand(boost::bind(&Mediator::OnRemoteCommand,this,_1));
}

Mediator::~Mediator(void)
{
}

void Mediator::OnRemoteCommand(LuaCommand &command)
{
    m_readCommands.push(command);

    fbpMainFrame *frame = GetFrame();
    if( frame != NULL ){
        wxIdleEvent event;
        event.SetId(wxID_ANY);
        frame->GetEventHandler()->AddPendingEvent(event);
    }
}

void Mediator::ProcessAllRemoteCommands(void)
{
    while (!m_readCommands.empty()) {
        LuaCommand command = m_readCommands.front();
        m_readCommands.pop();

        if (command.IsResponse()) {
            command.CallResponse();
        }
        else {
            ProcessRemoteCommand(command);
        }
    }
}

void Mediator::ProcessRemoteCommand(const LuaCommand &command)
{
    // Process remote commands.
    switch (command.GetType())
    {
    case REMOTECOMMANDTYPE_START_CONNECTION:
        break;

    case REMOTECOMMANDTYPE_END_CONNECTION:
        {
            m_breakpoints = BreakpointList(m_engine);
            m_sourceManager = SourceManager(m_engine);
            m_stackFrame = LuaStackFrame();
            m_updateCount = 0;

            wxDebugEvent event(wxEVT_DEBUG_END_DEBUG, wxID_ANY);
            ProcessDebugEvent(event);
        }
        break;

    case REMOTECOMMANDTYPE_CHANGED_STATE:
        {
            bool isBreak;
            command.GetData().Get_ChangedState(isBreak);

            wxDebugEvent event(wxEVT_DEBUG_CHANGED_STATE, wxID_ANY, isBreak);
            ProcessDebugEvent(event);
        }
        break;

    case REMOTECOMMANDTYPE_SET_UPDATECOUNT:
        {
            int updateCount;
            command.GetData().Get_SetUpdateCount(updateCount);

            if (updateCount > m_updateCount) {
                m_updateCount = updateCount;
            }
        }
        break;

    case REMOTECOMMANDTYPE_UPDATE_SOURCE:
        {
            std::string key;
            int line, updateCount;
            bool isRefreshOnly;
            command.GetData().Get_UpdateSource(key, line, updateCount, isRefreshOnly);

            // Update info.
            if (updateCount > m_updateCount) {
                m_updateCount = updateCount;
            }
            else {
                ++m_updateCount;
                m_engine->SendSetUpdateCount(m_updateCount);
            }

            // If isRefreshOnly is true, don't change the stack frame.
            if (!isRefreshOnly) {
                m_stackFrame = LuaStackFrame(LuaHandle(), 0);
            }

            wxDebugEvent event(wxEVT_DEBUG_UPDATE_SOURCE,wxID_ANY,key,line,updateCount,isRefreshOnly);
            ProcessDebugEvent(event);
            m_engine->ResponseSuccessed(command);
        }
        break;

    case REMOTECOMMANDTYPE_ADDED_SOURCE:
        {
            Source source;
            command.GetData().Get_AddedSource(source);
            m_sourceManager.AddSource(source, false);

            wxDebugEvent event(wxEVT_DEBUG_ADDED_SOURCE, wxID_ANY, source);
            ProcessDebugEvent(event);
        }
        break;

    case REMOTECOMMANDTYPE_CHANGED_BREAKPOINTLIST:
        {
            BreakpointList bps(m_engine);
            command.GetData().Get_ChangedBreakpointList(bps);
            m_breakpoints = bps;

            wxDebugEvent event(wxEVT_DEBUG_CHANGED_BREAKPOINTS, wxID_ANY);
            ProcessDebugEvent(event);
        }
        break;

    case REMOTECOMMANDTYPE_SET_ENCODING:
        {
            //lldebug_Encoding encoding;
            //command.GetData().Get_SetEncoding(encoding);
            //wxSetEncoding(encoding);
        }
        break;

    case REMOTECOMMANDTYPE_OUTPUT_LOG:
        {
            LogData logData;
            command.GetData().Get_OutputLog(logData);
            //OutputLogInternal(logData, false);
        }
        break;

    case REMOTECOMMANDTYPE_FORCE_UPDATESOURCE:
    case REMOTECOMMANDTYPE_SAVE_SOURCE:
    case REMOTECOMMANDTYPE_SET_BREAKPOINT:
    case REMOTECOMMANDTYPE_REMOVE_BREAKPOINT:
    case REMOTECOMMANDTYPE_START:
    case REMOTECOMMANDTYPE_END:
    case REMOTECOMMANDTYPE_STEPINTO:
    case REMOTECOMMANDTYPE_STEPOVER:
    case REMOTECOMMANDTYPE_STEPRETURN:
    case REMOTECOMMANDTYPE_BREAK:
    case REMOTECOMMANDTYPE_RESUME:
    case REMOTECOMMANDTYPE_EVALS_TO_VARLIST:
    case REMOTECOMMANDTYPE_EVAL_TO_MULTIVAR:
    case REMOTECOMMANDTYPE_EVAL_TO_VAR:
    case REMOTECOMMANDTYPE_REQUEST_LOCALVARLIST:
    case REMOTECOMMANDTYPE_REQUEST_FIELDSVARLIST:
    case REMOTECOMMANDTYPE_REQUEST_GLOBALVARLIST:
    case REMOTECOMMANDTYPE_REQUEST_REGISTRYVARLIST:
    case REMOTECOMMANDTYPE_REQUEST_STACKLIST:
    case REMOTECOMMANDTYPE_REQUEST_BACKTRACELIST:
    case REMOTECOMMANDTYPE_REQUEST_SOURCE:
    case REMOTECOMMANDTYPE_SUCCESSED:
    case REMOTECOMMANDTYPE_FAILED:
    case REMOTECOMMANDTYPE_VALUE_STRING:
    case REMOTECOMMANDTYPE_VALUE_VAR:
    case REMOTECOMMANDTYPE_VALUE_VARLIST:
    case REMOTECOMMANDTYPE_VALUE_SOURCE:
    case REMOTECOMMANDTYPE_VALUE_BREAKPOINTLIST:
    case REMOTECOMMANDTYPE_VALUE_BACKTRACELIST:
        BOOST_ASSERT(false && "Invalid remote command.");
        break;
    }
}

void Mediator::ProcessDebugEvent(wxDebugEvent & event)
{
    fbpMainFrame *frame = GetFrame();
    if( frame != NULL ){
        m_frame->ProcessDebugEvent(event,true);
    }
}

LUA_DEBUG_END
